package com.own.business.login.core.auth;

import com.own.business.login.core.core.RoleSpringHook;
import com.own.business.login.core.hook.GetUserAccountTypeHook;
import com.own.business.login.core.hook.GetUserNameHookImpl;
import com.own.component.client.base.RequestClientManager;
import com.own.component.common.login.AuthenticationLoginUser;
import com.own.component.common.login.core.UserStatusHook;
import com.own.component.common.login.user.BaseLoginUser;
import com.own.component.common.login.user.BasePermissionUser;
import com.own.component.common.login.user.DefaultLoginUser;
import com.own.component.common.login.user.DefaultPermissionUser;
import com.own.component.store.core.Store;
import com.own.component.store.core.util.StoreKeyUtil;
import com.own.component.token.base.RequestTokenManager;
import com.own.component.token.base.StoreTokenManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.Duration;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * DefaultAuthenticationLoginUser
 *
 * @author chenxueli
 * @date 2023-06-21 15:50:09
 */
@Component
public class DefaultAuthenticationLoginUser implements AuthenticationLoginUser, UserStatusHook {

    @Resource
    private HttpServletRequest request;

    @Resource
    private StoreTokenManager storeTokenManager;
    @Resource
    private RequestTokenManager requestTokenManager;
    @Resource
    private RequestClientManager requestClientManager;

    @Resource
    private RoleSpringHook roleSpringHook;
    @Resource
    private GetUserNameHookImpl getUserNameHookImpl;
    @Resource
    private GetUserAccountTypeHook getUserAccountTypeHook;

    @Resource
    private Store<String> store;

    @Override
    public BaseLoginUser loginUser() {
        // 获取session请求头中的参数
        var token = requestTokenManager.token(request);
        if (StringUtils.isBlank(token)) {
            return new DefaultLoginUser();
        }
        // 获取客户端参数
        var client = requestClientManager.client(request);
        return Optional
                // 获取用户id并判断是否为空
                .ofNullable(storeTokenManager.getUserId(token))
                // 构造登录的用户对象
                .map(userId -> buildLoginUser(userId, token, client))
                // 用户id为空的情况下，返回默认的登录用户对象
                .orElseGet(DefaultLoginUser::new);
    }

    /**
     * 权限类用户信息
     *
     * @param loginUser 登录的用户信息
     * @return 权限类用户信息
     */
    @Override
    public BasePermissionUser permissionUser(BaseLoginUser loginUser) {
        return new DefaultPermissionUser(
                loginUser,
                roleSpringHook.get(loginUser),
                ((module, operation) -> {
                    // 查询出当前用户的所有权限信息
                    var operationList = roleSpringHook.module(loginUser, module);
                    return operationList.contains(operation);
                })
        );
    }

    /**
     * 基本类用户信息
     *
     * @param userId 用户id
     * @return 基本类用户信息
     */
    @Override
    public List<BaseLoginUser> loginUser(Long userId) {
        return storeTokenManager
                .listToken(userId)
                .stream()
                .map(token -> buildLoginUser(userId, token, null))
                .collect(Collectors.toList());
    }

    /**
     * 登录类用户信息统一构建
     *
     * @param userId 用户id
     * @param token  token令牌
     * @param client 客户端id
     * @return 登录类用户信息统一构建
     */
    public BaseLoginUser buildLoginUser(Long userId, String token, String client) {
        // 查看缓存中是否存在相应的用户信息
        var value = store.value();
        // 获取当前账号的类型
        var accountType = getUserAccountTypeHook.get(userId);
        var key = StoreKeyUtil.build("username", userId);
        if (!value.contains(key)) {
            var name = getUserNameHookImpl.getUserName(userId);
            // 存入缓存
            if (StringUtils.isNotBlank(name)) {
                value.set(key, name, Duration.ofDays(7L));
            }
            return new DefaultLoginUser(token, userId, name, accountType, client);
        }
        return new DefaultLoginUser(token, userId, value.get(key), accountType, client);
    }

    /**
     * 清除信息
     *
     * @param loginUser 登录的用户信息
     */
    @Override
    public void clear(BaseLoginUser loginUser) {
        storeTokenManager.deleteByToken(loginUser.token());
    }

}
